home *** CD-ROM | disk | FTP | other *** search
- var EXPORTED_SYMBOLS = ["commandQueueMgr"];
-
- Components.utils.import("resource://yoono/yoonoPrefs.js");
-
- // Yoono stuff
- var yoono = {};
- var log = {info:function() {},debug:function() {},warn:function(){},error:function (){},fatal:function(){}};
-
- // Vars
- const YOONO_DIR = "yoono";
- const SYNC_FILE = "yoono_commands.log";
- const SYNC_RUNNING_FILE = "yoono_running_commands.log";
-
-
- // Globals
- const CI = Components.interfaces;
- const CL = Components.classes;
- const DIRSERVICE = CL['@mozilla.org/file/directory_service;1'].getService(CI.nsIProperties);
- const PREFSSERVICE = CL["@mozilla.org/preferences-service;1"].getService(CI.nsIPrefService);
- const PREFS = PREFSSERVICE.getBranch("extensions.yoono.");
-
-
- const REQUEST_DELAY = 1000; // en ms.
-
-
- //**************************************************************************/
- //
- // All request can now pile up but only transactional are saved over sessions
- //
-
- function CommandQueue() {
- this.wrappedJSObject=this;
-
-
- this._nextTransactionFile = DIRSERVICE.get("ProfDS", CI.nsIFile);
- this._runningTransactionFile = DIRSERVICE.get("ProfDS", CI.nsIFile);
-
- this._nextTransactionFile.append(YOONO_DIR); this._nextTransactionFile.append(SYNC_FILE);
- this._runningTransactionFile.append(YOONO_DIR); this._runningTransactionFile.append(SYNC_RUNNING_FILE);
-
- this._running=[];
- this._next=[];
-
- this.isRunning=false;
-
- this._observers=[];
-
- }
-
- CommandQueue.prototype.init = function (y) {
-
- yoono = y;
- log = y.log;
- try {
- // Releases before 3.0.6 wrote the sync file in the user chrome directory
- // Newer releases write the sync file in the yoono directory
- // If the file exists at the old location, move it first
- var oldFile = DIRSERVICE.get("UChrm", CI.nsIFile);
- oldFile.append(SYNC_FILE);
- if (oldFile.exists()) {
- var newFile = DIRSERVICE.get('ProfDS', CI.nsIFile);
- newFile.append(YOONO_DIR);
- oldFile.moveTo(newFile,SYNC_FILE);
- }
-
-
- this.reload();
- } catch(e) {
- log.exception(e);
- }
- }
-
- CommandQueue.prototype.uninstall = function() {
- try {
- log.warn("Remove sync-file");
- var file = DIRSERVICE.get("UChrm", CI.nsIFile);
- file.append(SYNC_FILE);
- if( file.exists() ) {
- file.remove(true);
- }
- } catch(e) {}
- try {
- file = DIRSERVICE.get("ProfDS", CI.nsIFile);
- file.append(YOONO_DIR);
- file.append(SYNC_FILE);
- if( file.exists() ) {
- file.remove(true);
- }
- } catch(e) {}
- try {
- file = DIRSERVICE.get("ProfDS", CI.nsIFile);
- file.append(YOONO_DIR);
- file.append(SYNC_RUNNING_FILE);
- if( file.exists() ) {
- file.remove(true);
- }
- } catch(e) {}
- }
-
- // Load commands from command file from last session.
- CommandQueue.prototype.reload = function() {
- var start = (new Date()).getTime();
-
- var istream = CL["@mozilla.org/network/file-input-stream;1"].createInstance(CI.nsIFileInputStream);
-
- // Reload next requests
- if( this._nextTransactionFile.exists() ) {
- try {
- istream.init(this._nextTransactionFile, 0x01, 0444, 0);
- var converter = CL["@mozilla.org/intl/converter-input-stream;1"].createInstance( CI.nsIConverterInputStream);
- converter.init(istream, 'UTF-8', 1024, '-');
- var line = {};
- this._next = [];
- var content="";
- while(converter.readString(4096, line)) {
- content+=line.value;
- }
- var requests=content.split('\n');
- for each(var r in requests) {
- if (r.length<=3) continue;
- this._next.push( new XML(r) );
- }
- istream.close();
- } catch(e) {
- log.exception(e);
- var outputStream = CL["@mozilla.org/network/file-output-stream;1"].createInstance( CI.nsIFileOutputStream);
- outputStream.init(this._nextTransactionFile, 0x02 | 0x08 | 0x20 , 0644, 0);
- outputStream.write("", 0);
- outputStream.flush();
- outputStream.close();
- }
- }
- // Reload running requests
- if( this._runningTransactionFile.exists() ) {
- try {
- istream.init(this._runningTransactionFile, 0x01, 0444, 0);
- var converter = CL["@mozilla.org/intl/converter-input-stream;1"].createInstance( CI.nsIConverterInputStream);
- converter.init(istream, 'UTF-8', 1024, '-');
- var line = {};
- this._running = [];
- var content="";
- while(converter.readString(4096, line)) {
- content+=line.value+"\n";
- }
- var requests=content.split('\n');
- for each(var r in requests) {
- if (r.length<=3) continue;
- this._running.push( new XML(r) );
- }
- istream.close();
- } catch(e) {
- log.exception(e);
- var outputStream = CL["@mozilla.org/network/file-output-stream;1"].createInstance( CI.nsIFileOutputStream);
- outputStream.init(this._runningTransactionFile, 0x02 | 0x08 | 0x20 , 0644, 0);
- outputStream.write("", 0);
- outputStream.flush();
- outputStream.close();
- }
- }
- log.debug("reload elapse-time = "+ ((new Date()).getTime() - start));
-
- this.flush();
- }
-
- // Simulate a browser shutdown for unit testing
- CommandQueue.prototype.simulateShutdown = function() {
- this._running=[];
- this._next=[];
- }
-
- // Reset all list : in-memory and files
- // used mainly by unit testing
- CommandQueue.prototype.fullReset = function() {
- this._running=[];
- var outputStream = CL["@mozilla.org/network/file-output-stream;1"].createInstance( CI.nsIFileOutputStream);
- outputStream.init(this._runningTransactionFile, 0x02 | 0x08 | 0x20 , 0644, 0);
- outputStream.write("", 0);
- outputStream.flush();
- outputStream.close();
- this._next=[];
- var outputStream = CL["@mozilla.org/network/file-output-stream;1"].createInstance( CI.nsIFileOutputStream);
- outputStream.init(this._nextTransactionFile, 0x02 | 0x08 | 0x20 , 0644, 0);
- outputStream.write("", 0);
- outputStream.flush();
- outputStream.close();
-
- }
-
- // Register a new observer to handle responses and errors
- // observer = {onSendingRequest:function(request){}, onRequestSuccess:function(request, response){return newRequest;}, onRequestError:function(request){}}
- // if onRequestSuccess return a request (string), it is added to the current request and resent
- CommandQueue.prototype.addObserver = function(o) {
- this._observers.push(o);
- }
- CommandQueue.prototype.removeObserver = function(o) {
- for(i=0;i<this._observers.length;i++){
- if(o==this._observers[i]) this._observers.splice(i, 1);
- }
- }
-
- // Request which must absolutely be sent
- // (equivalent of persistant next in old API)
- CommandQueue.prototype.addTransactionalRequest = function (s) {
-
- log.debug("Adding transactional request : "+s.toXMLString());
- // Add to in-memory list
- this._next.push(s)
-
- // Add to transaction file
- var outputStream = CL["@mozilla.org/network/file-output-stream;1"].createInstance( CI.nsIFileOutputStream);
- var converter = CL['@mozilla.org/intl/converter-output-stream;1'].createInstance(CI.nsIConverterOutputStream);
- converter.init(outputStream, 'UTF-8', 1024, '-');
- // WRONLY, CREATE_FILE, TRUNCATE
- // from http://lxr.mozilla.org/aviary101branch/source/nsprpub/pr/include/prio.h
- outputStream.init(this._nextTransactionFile, 0x02 | 0x08 | 0x10 , 0644, 0);
- converter.writeString(s.toXMLString().replace(/\n/g,"")+"\n");
- converter.flush();
- outputStream.flush();
- outputStream.close();
-
- // Flush requests
- this.flush();
-
- }
-
- // All other requests which doesn't need to be keept over session
- // (equivalent of transcient next)
- CommandQueue.prototype.addTranscientRequest = function (s) {
- var strCmd = s.toXMLString();
- log.debug("Adding transcient request : " + strCmd);
- // if connect command, remove any previous connect commands...
- if(0 == strCmd.indexOf('<connect')) {
- var nb = this._next.length;
- for(var idx=nb-1; idx >= 0; idx --) {
- var tr = this._next[idx];
- strCmd = tr.toXMLString();
- if(0 == strCmd.indexOf('<connect')) {
- this._next.splice(idx, 1);
- }
- }
- }
- this._next.push(s);
- this.flush();
-
- }
-
- // Replace current running requests with this one in order to run before next commands
- // (equivalent of transcient running with clearRunninCommands)
- CommandQueue.prototype._replaceRunningRequest = function (s) {
-
- log.debug("Replace request to the running one : "+s.toXMLString());
- this._running=[s];
-
- }
-
- // Return the next request to send
- CommandQueue.prototype._getRequest = function () {
- if (this._running.length==0) { // switch next requests to running ones
- log.debug("Switch requests");
- // 1) write next into running
- // Switch in-memory lists
- this._running=this._next;
- // Write next into running transaction file
- var outputStream = CL["@mozilla.org/network/file-output-stream;1"].createInstance( CI.nsIFileOutputStream);
- var converter = CL['@mozilla.org/intl/converter-output-stream;1'].createInstance(CI.nsIConverterOutputStream);
- converter.init(outputStream, 'UTF-8', 1024, '-');
- // WRONLY, CREATE_FILE, TRUNCATE
- // from http://lxr.mozilla.org/aviary101branch/source/nsprpub/pr/include/prio.h
- outputStream.init(this._runningTransactionFile, -1, 0644, 0);
- converter.writeString(this._next.map(function (r){return r.toXMLString().replace(/\n/g,"");}).join('\n')+"\n");
- converter.flush();
- outputStream.flush();
- outputStream.close();
- // 2) clean up next
- // Clean in-memory
- this._next=[];
- // Clean next transaction file
- var outputStream = CL["@mozilla.org/network/file-output-stream;1"].createInstance( CI.nsIFileOutputStream);
- outputStream.init(this._nextTransactionFile, 0x02 | 0x08 | 0x20 , 0644, 0);
- outputStream.write("", 0);
- outputStream.flush();
- outputStream.close();
- } else {
- log.debug("Redo current request");
- }
- return this._running;
- }
-
- CommandQueue.prototype._switchToNextRequests = function () {
- this._running=[];
- var outputStream = CL["@mozilla.org/network/file-output-stream;1"].createInstance( CI.nsIFileOutputStream);
- outputStream.init(this._runningTransactionFile, 0x02 | 0x08 | 0x20 , 0644, 0);
- outputStream.write("", 0);
- outputStream.flush();
- outputStream.close();
- }
-
- CommandQueue.prototype.isEmpty = function() {
- return (this._next.length == 0 && this._running.length == 0);
- }
-
- CommandQueue.prototype._timer = CL['@mozilla.org/timer;1'].createInstance(CI.nsITimer);
-
- // Wait in order to aggregate some requests and try to send
- CommandQueue.prototype.flush = function () {
- if (this.isRunning)
- return log.debug("no flush because a request is running");
- this._timer.initWithCallback(this, REQUEST_DELAY, this._timer.TYPE_ONE_SHOT);
- }
-
- CommandQueue.prototype.notify = function () {
- try {
- this._timer.cancel();
- this.send();
- } catch(e) {
- log.exception(e);
- }
- }
-
- CommandQueue.prototype.setSyncId = function() {
-
- if( !this.serverSyncId || this.serverSyncId.length == 0 ) {
- YOONO_PREFS.set('prevsyncid',YOONO_PREFS.get('syncid') || '', PREFS.PREF_STRING);
- YOONO_PREFS.set('syncid', yoono.bkm.getSyncId(), PREFS.PREF_STRING);
- } else {
- YOONO_PREFS.set('prevsyncid',this.serverSyncId, PREFS.PREF_STRING);
- YOONO_PREFS.set('syncid', this.serverSyncId, PREFS.PREF_STRING);
- this.serverSyncId = "";
- }
- //yoono.bkm.dump();
-
- }
-
- CommandQueue.prototype._replaceSyncId = function (syncid) {
- this.serverSyncId=syncid;
- }
-
- CommandQueue.prototype.nextPersistentCommandIsEmpty = function () {
-
- return ( !this._nextTransactionFile.exists() || this._nextTransactionFile.fileSize<=4);
-
- }
-
- CommandQueue.prototype.send = function () {
- if (this.isRunning)
- return log.debug("Not sending, because a request is running");
-
- var _this=this;
-
- var requests=this._getRequest();
- if (requests.length==0)
- return log.debug("No more requests to send!");
- this.isRunning=true;
-
- // Encapsulate the request
- if (!this._retryOnError)
- this.setSyncId();
- var xml = <server-script version="1.0"/>;
- xml.appendChild( <context>
- {(YOONO_PREFS.get('userid') ? <user-id> {YOONO_PREFS.get('userid')} </user-id> : '')}
- {(YOONO_PREFS.get('syncid') ? <sync-id> {YOONO_PREFS.get('syncid')} </sync-id> : '')}
- {(YOONO_PREFS.get('prevsyncid') ? <prev-sync-id> {YOONO_PREFS.get('prevsyncid')} </prev-sync-id> : '')}
- <locale>{yoono.utils.getLocale()}</locale>
- <version>{yoono.utils.getExtensionVersion()}</version>
- <client>xpi</client>
- </context>);
- for each(var r in requests) {
- xml.appendChild(r);
- }
- log.info('Sending async POST on ' + YOONO_PREFS.get('serverurl') + 'linkserver \n' + xml.toXMLString().replace(/<user-id>(.*)<\/user-id>/gi,"<user-id>*************</user-id>") + "\n>>>>>>>>>>>> ");
-
- // Warm up ajax request
- var data= 'script=' + encodeURIComponent( xml.toXMLString() );
-
- var xmlhttp = CL["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(CI.nsIXMLHttpRequest);
-
- xmlhttp.open('POST', YOONO_PREFS.get('serverurl') + 'linkserver', true);
-
- xmlhttp.setRequestHeader("Cache-Control", "no-cache");
- xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
-
- // Called on any type of error
- function onError() {
- try { xmlhttp.abort(); } catch(e) {}
-
- for each(var o in _this._observers) {
- try {
- o.onRequestError(requests);
- } catch(e) {
- log.exception(e);
- }
- }
-
- _this._retryOnError=true;
-
- // Then try to resend the current request some times after
- var delayFunction={
- notify : function (t) {
- _this.flush();
- }
- };
- var timer = CL['@mozilla.org/timer;1'].createInstance(CI.nsITimer);
- timer.initWithCallback(delayFunction, 6000, timer.TYPE_ONE_SHOT);
-
- }
-
- // Initialize a timer to timeout the request if necessary
- var timeoutObserver = {
- timer : CL['@mozilla.org/timer;1'].createInstance(CI.nsITimer),
- delay : YOONO_PREFS.get('request.timeout') * 1000, // la pref est en secondes
- start : function () {
- this.timer.initWithCallback(this, this.delay, this.timer.TYPE_ONE_SHOT);
- },
- stop : function () {
- this.timer.cancel();
- },
- notify : function (t) {
- this.stop();
- _this.isRunning=false;
-
- onError();
- }
- };
-
- // Called on success
- xmlhttp.onload = function (event) {
- try {
- timeoutObserver.stop();
- _this.isRunning=false;
-
- if((4 != event.target.readyState) || (200 != event.target.status)) {
- log.error(event.target.readyState+"/"+event.target.status);
- return onError();
- }
-
- var data = new XML(xmlhttp.responseText.replace(/<\?xml.*?\?>\n?/g, ""));
-
- log.info('Receiving response \n' + data.toXMLString() + "\n<<<<<<<<<<<<< ");
-
- // Notify all observers and collect new requests
- // all new requests are added to the running requests list
- var redo=false;
- for each(var o in _this._observers) {
- var replace=false;
- try {
- replace = o.onRequestSuccess(requests,data);
- } catch(e) {
- log.exception(e);
- }
- if (replace) {
- if (replace.overrideSyncId)
- _this._replaceSyncId(replace.overrideSyncId);
- _this._replaceRunningRequest(replace.xml);
- redo=true;
- break;
- }
- }
-
- if (!redo)
- _this._switchToNextRequests();
-
- _this._retryOnError=false;
- _this.flush();
-
- } catch(e) {
- log.exception(e);
- }
- };
-
- // Called on network error
- xmlhttp.onerror = function (e) { // Error
- try {
- timeoutObserver.stop();
- _this.isRunning=false;
-
- onError();
-
- } catch(e) {
- log.exception(e);
- }
- };
-
- // Notify observers
- for each(var o in this._observers) {
- try {
- o.onSendingRequest(requests);
- } catch(e) {
- log.exception(e);
- }
- }
-
- // Go go go!
- xmlhttp.send(data);
-
- timeoutObserver.start();
-
- }
-
-
-
-
- var commandQueueMgr = new CommandQueue();
-